# LeetCode 334、递增的三元组
# 一、题目描述
给你一个整数数组 nums
,判断这个数组中是否存在长度为 3
的递增子序列。
如果存在这样的三元组下标 (i, j, k)
且满足 i < j < k
,使得 nums[i] < nums[j] < nums[k]
,返回 true
;否则,返回 false
。
示例 1:
输入:nums = [1,2,3,4,5] 输出:true 解释:任何 i < j < k 的三元组都满足题意
示例 2:
输入:nums = [5,4,3,2,1] 输出:false 解释:不存在满足题意的三元组
示例 3:
输入:nums = [2,1,5,0,4,6] 输出:true 解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6
提示:
1 <= nums.length <= 5 * 10^5
-2^31 <= nums[i] <= 2^31 - 1
**进阶:**你能实现时间复杂度为 O(n)
,空间复杂度为 O(1)
的解决方案吗?
# 二、题目解析
# 三、参考代码
# 1、Java 代码
// 超时代码
class Solution {
public boolean increasingTriplet(int[] nums) {
// 设置数组 dp,用来存储 nums 中以每个元素结尾的最长递增序列的程度
// dp[0] 表示以 nums[0] 结尾的最长递增序列的长度
// dp[1] 表示以 nums[1] 结尾的最长递增序列的长度
// dp[i] 表示以 nums[i] 结尾的最长递增序列的长度
int[] dp = new int[nums.length];
// 首先将数组 dp 里面的值都初始化为 1
// 1 表示以当前元素结尾的最长递增序列的长度为 1
// 即最长递增序列就是当前元素本身
Arrays.fill(dp, 1);
// 设置一个变量用来存储最长递增序列的结果
int maxLength = 1;
// 从 1 开始,直到 dp.length ,往 dp 里面填充结果
for(int i = 1 ; i < dp.length ; i++){
// 对于 dp[i] 来说,在 nums 中从 0 到 i - 1 都是在 i 的前面的
// 比如 nums 为 [1,5,2,5,3,7,2]
// 此时 i 为 3,那么 1,5,2 这些数字都在索引位置为 3 的前面
// 从 0 遍历到 i - 1,就可以从这些数字中选出小于 i 的数字
for(int j = 0; j < i ;j++){
// 索引 0 1 2 3 4 5 6
// nums 为 [ 1, 5, 2, 5, 3, 7, 2 ]
// 此时 i 为 3,那么 1,5,2 这些数字都在索引位置为 3 的前面
// 1、从这些数字中选出小于 nums[i] 的数字
// 2、小于 nums[i] 的那些数字是 1 , 2 ,在之前都已经计算过以 1 或者 2 结尾的最长递增序列的长度
// 并且这个结果存放在 dp[j] 中
// 如果数字为 1,那么此时 j 为 0,dp[0] 存放了以 1 结尾的最长递增序列的长度
// 如果数字为 2,那么此时 j 为 2,dp[2] 存放了以 2 结尾的最长递增序列的长度
// 3、如果发现此时 dp[i] 小于了 dp[j] + 1
// 4、说明此时 dp[i] 中的值就不是以 nums[i] 结尾的最长递增序列的长度
// 需要更新 dp[i]
if(nums[i] > nums[j] && dp[i] < dp[j] + 1){
// 4、更新 dp[i]
dp[i] = dp[j] + 1;
}
}
// 在更新 dp[i] 的过程中,发现了一个更长的子序列
if(maxLength < dp[i]){
// 那么把更长的子序列的长度赋值给 maxLength
maxLength = dp[i];
}
if( maxLength >= 3) return true;
}
// 最后返回 maxLength 就行
return false;
}
}
Python
class Solution:
def increasingTriplet(self, nums: List[int]) -> bool:
# 三元组里面最小的数
first = float('inf')
# 三元组里面中间的那个数
second = float('inf')
# 开始寻找第三个数
for third in nums:
# 1、第三个数 大于 了之前确定好的 第二个数
# 说明找到了满足条件的三元组
if third > second: return True
# 2、第三个数 小于 了之前确定好的 第一个数
# 为了能让后续 第二个数 的可选范围更大
# 第一个数总是应该越小越好
# 这样 第二个数 的可选范围更大
# 导致 第三个数 的可选范围也更大
# 更能找到满足条件的三元组
elif third <= first: first = third
# 3、第三个数的值介于 first 和 second 中间
# 更新 second 的值
# 第二个数小一些
# 导致 第三个数 的可选范围也更大
# 更能找到满足条件的三元组
else: second = third
# 返回结果
return False